package org.sergiy.forecast;

import java.net.URL;
import java.util.List;
import java.io.File;
import java.io.InputStream;

import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import au.gov.bom.weather.AreaType;
import au.gov.bom.weather.BomWeatherService;
import au.gov.bom.weather.DefaultBomWeatherService;
import au.gov.bom.weather.ForecastPeriodType;
import au.gov.bom.weather.ForecastType;
import au.gov.bom.weather.ProductType;
import au.gov.bom.weather.TextElementType;

/**
 * Test of BOM forecast weather service (XML file)
 *   
 * @author Sergiy Litsenko
 *
 */
@Test
public class ForecastTestCase extends ForecastCoreTestCase {
	
	@BeforeClass
	@Override
	protected void init() throws Exception {
		super.init();
	}

	@AfterClass
	@Override
	protected void destroy() throws Exception {
		super.destroy();
	}

	@BeforeMethod
	@Override
	protected void setUp() throws Exception {
		super.setUp();
	}

	@AfterMethod
	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
	}
	
	/**
	 * Get instance of BomWeatherService
	 * @return instance of BomWeatherService
	 */
	protected BomWeatherService getBomWeatherService () {
		return new DefaultBomWeatherService();
	}
	
	/**
	 * Logs forecast to the log file
	 * @param forecast
	 */
	protected void logForecast (ForecastType forecast) {
		// debug
		if (log.isDebugEnabled()) {
			for (AreaType area : forecast.getArea()) {
				log.debug(String.format("Area: %1$s", area.getDescription()));
				for (ForecastPeriodType forecastPeriod : area.getForecastPeriod()) {
					log.debug(String.format("\t%1$tA, %1$td %1$tB :", forecastPeriod.getEndTimeLocal().toGregorianCalendar()));
					for (TextElementType textElementType : forecastPeriod.getText()) {
						if (textElementType.getType().equalsIgnoreCase("forecast")) {
							log.debug(String.format("\t\t%1$s", textElementType.getContent()));
						}
					}
				}
			}
		}	
	}
	
	/**
	 * Valid values for testing Override File Name Behaviour
	 */
	@DataProvider(name = "validCodesForBomService")
	public Object[][] createValidCodesForBomService() throws Exception {
		return new Object[][] {
				{BomWeatherService.CODE_SYDNEY_REGION_FORECAST},
				{BomWeatherService.CODE_CANBERRA_REGION_FORECAST}
		};
	}
	
	
	@Test
	public void testBomWeatherServiceUsingLocalFile() throws Exception {
		// start marker
		logStartTestMarker ("testBomWeatherServiceUsingLocalFile");		
		// debug
		if (log.isDebugEnabled()) {
			log.debug(String.format("Testing the local file IDN10064.xml forecast."));
		}
		// Get instance of BomWeatherService
		BomWeatherService service = getBomWeatherService ();
		// test
		Assert.assertNotNull (service, "BOM Weather Service must exists");
		
		// get local file URL
		URL file = new File ("src/test/resources/IDN10064.xml").getCanonicalFile().toURI().toURL();
		// test if it exists
		InputStream is = file.openStream();
		if (is != null) {
			is.close();
		}
		// get product
		ProductType product = service.getForecast(file);
		// test
		Assert.assertNotNull (product, "BOM Weather Service must return weather service data");
		// get forecast
		ForecastType forecast = product.getForecast();
		Assert.assertNotNull (product, "Forecast must be provided");
		
		// Logs forecast to the log file
		logForecast (forecast);
	}


	@Test (dataProvider = "validCodesForBomService")
	public void testremoteBomWeatherService(String code) throws Exception {
		// start marker
		logStartTestMarker ("testremoteBomWeatherService");		
		
		// debug
		if (log.isDebugEnabled()) {
			log.debug(String.format("Testing the remote BOM service for %1$s code", code));
		}
		
		// Get instance of BomWeatherService
		BomWeatherService service = getBomWeatherService ();
		// test
		Assert.assertNotNull (service, "BOM Weather Service must exists");
		
		// get product
		ProductType product = service.getForecast(code);
		// test
		Assert.assertNotNull (product, "BOM Weather Service must return weather service data");
		
		// get forecast
		ForecastType forecast = product.getForecast();
		Assert.assertNotNull (product, "Forecast must be provided");
		
		// Logs forecast to the log file
		logForecast (forecast);
	}
}
